/*
 * Copyright (c) 2022 Queclink-C-Library
 *
 * This file is subject to the terms and conditions of the MIT License.
 * For details, please see the LICENSE file or visit the MIT website: https://mit-license.org/
 */

#include <stddef.h>
#include <string.h>

#include <qlibc/assert.h>

#include "qlibc_log.h"
void quec_crepl(char *str, const char *chars, const char c)
{
    assert(NULL != str);
    assert(NULL != chars);

    size_t str_len = strlen(str);
    size_t chars_len = strlen(chars);
    size_t i, j;

    for (i = 0; i < str_len; i++) {
        for (j = 0; j < chars_len; j++) {
            if (*(str + i) == *(chars + j)) {
                *(str + i) = c;
                break;
            }
        }
    }
}

void quec_strcrlf(char *str)
{
    assert(NULL != str);

    size_t str_len = strlen(str);

    if ('\r' == *(str + str_len - 2) &&
        '\n' == *(str + str_len - 1)) {
        return;
    } else if ('\r' == *(str + str_len - 1)) {
        *(str + str_len) = '\n';
        *(str + str_len + 1) = '\0';
    } else if ('\n' == *(str + str_len - 1)) {
        *(str + str_len - 1) = '\r';
        *(str + str_len) = '\n';
        *(str + str_len + 1) = '\0';
    } else {
        *(str + str_len) = '\r';
        *(str + str_len + 1) = '\n';
        *(str + str_len + 2) = '\0';
    }
}

void quec_strip(char *str, const char *chars)
{
    assert(NULL != str);
    assert(NULL != chars);

    char *start = NULL;
    int lenstr = (int)strlen(str);
    int lenchars = (int)strlen(chars);
    int i, j;

    for (i = 0; i < lenstr; i++) {
        for (j = 0; j < lenchars; j++) {
            if (*(str + i) == *(chars + j)) {
                start = str+i+1;
                break;
            }
        }
        if (!(j < lenchars))
            break;
    }

    if ((NULL != start) &&
        (start >= str + lenstr)) {
        *str = '\0';
        return;
    }

    for (i = lenstr - 1; i > 0; i--) {
        for (j = 0; j < lenchars; j++) {
            if (*(str + i) == *(chars + j)) {
                *(str + i) = '\0';
                break;
            }
        }
        if (!(j < lenchars))
            break;
    }

    if (NULL != start)
        strcpy(str, start);
}

char *quec_strrchr(const char *str, const char *chars)
{
    assert(NULL != str);
    assert(NULL != chars);

    int str_len = (int)strlen(str);
    int chars_len = (int)strlen(chars);
    int i, j;

    for (i = str_len - 1; i >= 0; i--) {
        for (j = 0; j < chars_len; j++) {
            if (*(str + i) == *(chars + j))
                return (char*)(str + i);
        }
    }

    return NULL;
}

int quec_strtail(const char *str, const char *tail)
{
    assert(NULL != str);
    assert(NULL != tail);

    size_t len_str = strlen(str);
    size_t len_tail = strlen(tail);

    if (len_tail > len_str || 0 == len_tail)
        return 0;

    if (0 == memcmp(&str[len_str - len_tail], tail, len_tail))
        return 1;
    else
        return 0;
}

char *quec_strtok_r(char *str, const char *delim, char **saveptr)
{
    assert(NULL != delim);
    assert(NULL != saveptr);

    char *src = *saveptr;
    char *p0 = NULL;
    const char *p1 = NULL;

    if (NULL != str) {
        src = str;
    } else if (NULL != src) {
        str = src;
    } else {
        return NULL;
    }

    for (p0 = str; '\0' != *p0; ++p0) {
        for (p1 = delim; '\0' != *p1; ++p1 ) {
            if (*p0 == *p1) {
                *p0 = '\0';
                *saveptr = p0 + 1;

                return str;
            }
        }
    }

    *saveptr = NULL;

    return str;
}

unsigned int quec_strtokcnt(char *str, const char *delim)
{
    assert(NULL != str);
    assert(NULL != delim);

    const char *p0 = NULL;
    const char *p1 = NULL;
    int n = 1;

    for (p0 = str; '\0' != *p0; ++p0) {
        for (p1 = (char *)delim; '\0' != *p1; ++p1) {
            if (*p0 == *p1) {
                n++;

                break;
            }
        }
    }

    return n;
}
